<?PHP
namespace SDF\Db;

/**
 * 把Redis当数据库来用，提供基本的CRUD功能。适合小项目，用Redis作为持久化存储。
 * @package SDF\Db
 */
class RedisManager{
    private $db;//默认NoSql数据库对象
    private $key;//数据对象存储key，这个属性必须初始化
    protected $_id_;//资源id
    protected $_collections;//资源集合
    private $attr = array();//属性集，用于存储基本的键值对属性 此属性存储为hash

    /**
     * 构造函数，初始化db类等
     *
     * @param string $_collections      集合名字，可以理解为关系型数据库中的表
     * @param string $_id_              集合对象id，可以理解为表中的自增id,如果没有这个参数，表示操作的对象是集合,
     */
    public function __construct($_collections, $_id_ = null) {
        $this->db = new Redis();
        $this->_collections = $_collections;
        if(empty($_id_)){
            $this->key = $_collections;
        }else{
            $this->key = $_collections.':'.$_id_;
            $this->_id_ = $_id_;
        }
    }

    /**
     * 获取指定属性的值
     * @param $name
     * @return mixed
     */
    public function __get($name){
        if(isset($this->attr[$name])){
            return $this->attr[$name];
        }
        $this->attr[$name]  =  $this->db->hGet($this->key,$name);
        return $this->attr[$name];
    }

    /**
     * 设置属性
     * @param $name
     * @param $value
     * @return bool
     */
    public function __set($name, $value)
    {
        $this->attr[$name] = $value;
        return true;
    }

    /**
     * 删除属性
     * 删除属性会直接操作数据库
     * @param $name
     * @return null
     */
    public function __unset($name) {
        if(isset($this->attr[$name])){
            unset($this->attr[$name]);
        }
        return $this->db->hDel($this->key,$name);
    }

    /**
     * 保存属性到数据库
     */
    public function save(array $data=array()){
        if(empty($data)){
            $reg = $this->db->hMset($this->key,$this->attr);
        }else{
            $reg = $this->db->hMset($this->key,$data);
        }

        //echo $this->key;
        $this->attr = array();//每次保存属性后，把属性值设为空
        return $reg;
    }

    /**
     * 设置属性
     * @param array $attr
     */
    public function set_attr(array $attr){
        $this->attr += $attr;
        //return $this;
    }

    /**
     * 获取所有属性和值
     * @return mixed
     */
    public function get_attr(){
        $this->attr = $this->db->hGetAll($this->key);
        return $this->attr;
    }

    /**
     * 获取下一个自增id
     */
    private function get_next_id(){
        return $this->db->IncrBy($this->key.':next_id',1);
    }

    /**
     * 返回自增id
     * @return mixed
     */
    public function get_auto_increment(){
        return $this->get_next_id();

    }

    /**
     * 插入数据
     * 此事的$this->key应是一个集合key
     * @param array $data
     * @return mixed
     */
    public function add(array $data=array()) {
        $id = $this->get_next_id();
        $key =$this->_collections.':'.$id;

        if(empty($data)){
            $reg = $this->db->hMset($key,$this->attr);
        }else{
            $reg = $this->db->hMset($key,$data);
        }
        $this->attr = array();//每次保存属性后，把属性值设为空
        if($reg){
            $this->db->sAdd($this->_collections,$id);//向集合中添加id
            return $id;
        }else{
            return false;
        }
    }

    /**
     * 获取集合中所有的数据
     * @return mixed
     */
    public function get_all(){
        $data = $this->db->sMembers($this->_collections);
        return $data;
    }

    /**
     * 删除数据指定哈希key的数据，立刻生效
     * @return mixed
     */
    public function del(){
        if(!empty($this->_id_)){
            $this->db->sRem($this->_collections,$this->_id_);
            $this->db->del($this->key);
        }else{
            return false;
        }
        return true;
    }

    /**
     * 析构函数
     */
    public function __destruct()
    {
        Redis::closeInstance(array('default'));
    }


    /**
     * 插入数据
     * 把属性以序列的方式插入到db
     * @param array $data
     * @return mixed
     */
    public function hash_add($key)
    {
        $reg = $this->db->rlHMset($key,$this->attr);
        $this->attr = array();//每次保存属性后，把属性值设为空
        if($reg){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 新增数据 集合 和hash都同时操作
     * @param array $data
     * @return bool
     */
    public function sets_add(array $data=array(),$id=null)
    {
        if(empty($id)) $id = $this->get_next_id();
        $key =$this->_collections.':'.$id;
        if(empty($data)){
            $reg = $this->db->hMset($key,$this->attr);
        }else{
            $reg = $this->db->hMset($key,$data);
        }
        $this->attr = array();//每次保存属性后，把属性值设为空
        if($reg){
            $this->sets_lists($this->_collections,$id);//向队例中添加id
            return $id;
        }else{
            return false;
        }
    }


    /**
     * 入队例
     * @param string $key
     * @param string $id 队例值
     * @return mixed
     */
    public function sets_lists($key='',$id=''){
        if(!$key) $key =$this->key;
        return $this->db->LPUSH($key,$id);
    }

    /**
     * 取出队例数据
     * @param null $key
     * @param int $start //开始数
     * @param null $len //结束数
     * @return mixed
     */
    public function gets_lists($key=null,$start=0,$len=null ){
        if(!$key) $key =$this->key;
        if(!$len) $len = $this->gets_len($key);
        return $this->db->LRANGE($this->key,$start,$len-1);
    }

    /**
     * 获取队例长度O
     * @param $key
     */
    public function gets_len($key){
        return $this->db->LLEN($key);

    }

    /**
     * 移动一个key
     * @param $key
     * @return mixed
     */
    public function dels($key){
        return $this->db->DEL($key);

    }
    /**
     * 删除该key下所有集合及数据
     * @param $key
     * @return mixed
     */
    public function del_alls(){
        $list = $this->gets_lists($this->key);
        foreach($list as $row){
            $this->db->del($this->key.':'.$row);
        }
        $this->db->del($this->key);
        // $this->db->LREM($this->key,0);
        return true;
    }

    /**
     * 获取当前key所有
     * @param string $key
     * @return mixed
     */
    public function get_hashkey($key=''){
        try{
            $keys = $this->db->dsHGetAll($key);//获取当前key所有
            return $keys;
        }catch (\Exception $e){
            echo $e->getMessage();
        }
    }

    /**
     * 设置关键字
     * @param string $key
     */
    public function set_keys($key='',$data){
        if(!$key) $key =$this->key;
        try{
            $keys = $this->db->SET($key,$data);
            return $keys;
        }catch (\Exception $e){
            echo $e->getMessage();
        }
    }

    /**
     * 获取关键字值
     * @param string $key
     */
    public function get_keys($key=''){
        if(!$key) $key =$this->key;
        try{
            $keys = $this->db->GET($key);//获取当前key所有
            return $keys;
        }catch (\Exception $e){
            echo $e->getMessage();
        }
    }

    /**
     * 向集合里增加一值
     * @param string $key
     * @return mixed
     */
    public function sets_data($key='',$id){
        if(!$key) $key =$this->key;
        try{
            $temp = $this->db->sAdd($key,$id);//向集合中添加id
            return $temp;
        }catch (\Exception $e){
            echo $e->getMessage();
        }
    }

    /**
     * 取出集合里所有的数据
     * @param string $key
     * @return mixed
     */
    public function gets_data($key=''){
        if(!$key) $key =$this->key;
        try{
            $temp = $this->db->SMEMBERS($key);//向集合中添加id
            return $temp;
        }catch (\Exception $e){
            echo $e->getMessage();
        }
    }

    /**
     * 删除集合中的数据
     * @param string $key
     * @return mixed
     */
    public function del_data($key='' , $id){
        if(!$key) $key =$this->key;
        try{
            $temp = $this->db->SREM($key , $id);//删除集合中的某个$key
            return $temp;
        }catch (\Exception $e){
            echo $e->getMessage();
        }
    }

    /**
     * 取出集合里key的数量
     * @param string $key
     * @return mixed
     */
    public function get_sets_nums($key=''){
        if(!$key) $key =$this->key;
        try{
            $temp = $this->db->SCARD($key);//向集合中添加id
            return $temp;
        }catch (\Exception $e){
            echo $e->getMessage();
        }
    }

    /**
     * 取出集合里key的数量
     * @param string $key
     * @return mixed
     */
    public function get_randmem_id(){
        try{
            $temp = $this->db->SRANDMEMBER($this->key);//向集合中添加id
            return $temp;
        }catch (\Exception $e){
            echo $e->getMessage();
        }
    }

    /**
     * 更新记录
     * @param string $key
     * @param $data  相当于字段 hash设置一个字段 array('title' => '1000', 'username' => 'xcxx');
     * @param $condition (array('type' => '', 'username' => 'xcxx');)
     */
    public function nosql_update($key="",$data,$condition=array()){
        $type =4;  //list队例为1 sets集合为2 字符串3 hash 4
        if(!$key) $key =$this->key;
        if($condition) $type = $condition['type'];
        if($type==1){ //队例下更新数据

        }
        if($type==2){//集合下更新数据

        }
        if($type==3){
            $reg =  $this->set_keys($key,$data);
            if($reg) return true;
        }
        if($type==4){
            $reg = $this->db->hMset($key,$data);
            if($reg) return true;
        }
        return false;
    }


}